/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.figures;

import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Locator;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;

/**
 * 
 */
public class RelationEndpointLocator implements Locator {

/**
 * use to caluclate coordinate at the end of relation
 * from topmodel project.
 */
	private Point result=null;
	
	/**
	 * 
	 * 
	 * @param c 
	 * @param end 
	 * @param p 
	 */
	public RelationEndpointLocator(Connection c, boolean end, Point p) {
		this.end = end;
		conn = c;
		figureBounds = new Rectangle();
		setDistances (p);
	}

	/**
	 * 
	 * 
	 * @param p 
	 */
	public void setDistances (Point p) {
		setXDistance(p.x);
		setYDistance(p.y);
	}
	
	/**
	 * 
	 * 
	 * @return 
	 */
	public Point getLocation(){
		Connection conn = getConnection();
		Point startPoint = Point.SINGLETON;
		Point endPoint = new Point();

		int startPointPosition = 0;
		int endPointPosition = 1;
		if (isEnd()) {
			startPointPosition = conn.getPoints().size() - 1;
			endPointPosition = startPointPosition - 1;
		}

		conn.getPoints().getPoint(startPoint, startPointPosition);
		conn.getPoints().getPoint(endPoint, endPointPosition);

		IFigure connOwner = getConnectionOwner();

		int quadrant;
		if (connOwner != null) {
			Rectangle connOwnerBounds = connOwner.getBounds();
			Point connOwnerCenter = connOwnerBounds.getCenter();
			Point connOwnerTL = connOwnerBounds.getTopLeft();
			quadrant = calculateConnectionLocation(startPoint, connOwnerTL, connOwnerCenter);
		} else {
			quadrant = calculateConnectionLocation(startPoint, endPoint);
		}

/*
		 *  1 == Top
		 *  2 == Right 
		 *  3 == Bottom 
		 *  4 == Left
*/
		
		int xxx = startPoint.x + xDistance;
		int yyy = startPoint.y + yDistance;
		result =new Point(xxx,yyy);
		return result; 
	}
	
	/**
	 * 
	 * 
	 * @param topLeft 
	 * @param loc 
	 * @param center 
	 * 
	 * @return 
	 */
	private int calculateConnectionLocation(Point loc, Point topLeft, Point center) {
		double m1, m2 = 0;
		m1 = (double) (topLeft.y - center.y) / (double) (topLeft.x - center.x);

		if (loc.x - center.x != 0) {
			m2 = (double) (loc.y - center.y) / (double) (loc.x - center.x);
		}

		if (loc.x == center.x) {
			// Case where m2 is vertical
			if (loc.y < center.y) {
				return 3;
			} else {
				return 1;
			}
		} else if (Math.abs(m2) <= Math.abs(m1)) {
			// Connection start point along left or right side
			if (loc.x < center.x) {
				return 4;
			} else {
				return 2;
			}
		} else {
			// Connection start point along top or bottom
			if (loc.y < center.y) {
				return 3;
			} else {
				return 1;
			}
		}
	}

	/**
	 * 
	 * 
	 * @param startPoint 
	 * @param endPoint 
	 * 
	 * @return 
	 */
	private int calculateConnectionLocation(Point startPoint, Point endPoint) {
		if (Math.abs(endPoint.x - startPoint.x) > Math.abs(endPoint.y
				- startPoint.y)) {
			if (endPoint.x > startPoint.x) {
				return 2;
			} else {
				return 4;
			}
		} else {
			if (endPoint.y > startPoint.y) {
				return 1;
			} else {
				return 3;
			}
		}
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	private Connection getConnection() {
		return conn;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	private IFigure getConnectionOwner() {
		IFigure connOwner;
		if (isEnd()) {
			connOwner = conn.getTargetAnchor().getOwner();
		} else {
			connOwner = conn.getSourceAnchor().getOwner();
		}

		return connOwner;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	private boolean isEnd() {
		return end;
	}

	/**
	 * 
	 * 
	 * @param figure 
	 */
	public void relocate(IFigure figure) {
		Connection conn = getConnection();
		Point startPoint = Point.SINGLETON;
		Point endPoint = new Point();

		int startPointPosition = 0;
		int endPointPosition = 1;
		if (isEnd()) {
			startPointPosition = conn.getPoints().size() - 1;
			endPointPosition = startPointPosition - 1;
		}

		conn.getPoints().getPoint(startPoint, startPointPosition);
		conn.getPoints().getPoint(endPoint, endPointPosition);

		IFigure connOwner = getConnectionOwner();

		int quadrant;
		if (connOwner != null) {
			Rectangle connOwnerBounds = connOwner.getBounds();
			Point connOwnerCenter = connOwnerBounds.getCenter();
			Point connOwnerTL = connOwnerBounds.getTopLeft();
			quadrant = calculateConnectionLocation(startPoint, connOwnerTL, connOwnerCenter);
		} else {
			quadrant = calculateConnectionLocation(startPoint, endPoint);
		}

/*
		 *  1 == Top
		 *  2 == Right 
		 *  3 == Bottom 
		 *  4 == Left
*/
		Dimension figureSize = figure.getPreferredSize();
		int xxx = startPoint.x + xDistance;
		int yyy = startPoint.y + yDistance;
		/*switch (quadrant) {
		case 1 :
			break;
		case 2 :
			break;
		case 3 :
			yyy -= figureSize.height;
			break;
		case 4 :
			xxx -= figureSize.width;
			break;
		default :
			break;
		}*/
		figureBounds.setSize(figureSize);
		figureBounds.setLocation(new Point (xxx, yyy));
		figure.setBounds(figureBounds);
	}

	/**
	 * 
	 * 
	 * @param distance 
	 */
	public void setXDistance(int distance) {
		xDistance = distance;
	}

	/**
	 * 
	 * 
	 * @param distance 
	 */
	public void setYDistance(int distance) {
		yDistance = distance;
	}

	/**
	 * 
	 */
	private boolean end;
	
	/**
	 * 
	 */
	private Connection conn;
	
	/**
	 * 
	 */
	private int xDistance, yDistance;
	
	/**
	 * 
	 */
	private static Rectangle figureBounds;

}